/**
 * @file Node.cpp
 * @author  Aljosa Osep <aljosa.osep@gmail.com>
 * @version 1.0
 *
 * @section LICENSE
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:

 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.

 *  2. Redistributions in binary form must reproduce the above copyright notice, this list
 *     of conditions and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.

 * THIS SOFTWARE IS PROVIDED BY <Aljosa Osep> ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <Aljosa Osep>> OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 * The views and conclusions contained in the software and documentation are those of the
 * authors and should not be interpreted as representing official policies, either expressed
 * or implied, of <Aljosa Osep>.
 *
 * @section DESCRIPTION
 *
 * Node - basic tree element
 * Based on example from Data Structures And Algorithms for Game Developers by Alen Sherod
 * Thanks!
 */

#include "Node.h"
#include "messages.h"
#include <iostream>

using namespace std;

namespace xEngine
{
    namespace PlatformIndependent
    {
        /**
         * Default constructor
         *
         */
        Node::Node() : next(NULL), prev(NULL), child(NULL) {
            cout<<"Node created."<<endl;
        }

        Node::Node(int key) : key(key), next(NULL), prev(NULL), child(NULL)  {
            cout<<"Node created."<<endl;
        }

        /**
         * Destructor
         *
         */
        Node::~Node() {
            this->prev = NULL;

            if (this->child != NULL)
                delete child;

            if (this->next != NULL)
                delete next;

            this->next = this->child = NULL;

            cout<<"Node deleted."<<endl;
        }

        /**
         * Add child
         *
         * Adds child to this node
         *
         * @param  Node to add
         */
        void Node::addChild(Node *node) {
            if (this->child == NULL)
                this->child = node;
            else
                this->child->addSibling(node);
        }

        /**
         * Add sibling
         *
         * Adds node next to this node (forms linked list)
         *
         * @param  Node to add
         */
        void Node::addSibling(Node *node) {
            Node *ptr = this->next;

            if (this->next == NULL) {
                // Next one is free. That's cool because we can attach node there ;)
                this->next = node;
                node->prev = this;
            }
            else
            {
                // Loop :)
                while(ptr->next != NULL) {
                    ptr = ptr->next;
                }

                ptr->next = node;
                node->prev = ptr;
            }
        }

        /**
         * Print
         *
         * Print's key data to console
         *
         */
        void Node::print() const {

            cout<<this->key;

            if (this->next != NULL) {
                cout<<" ";
                this->next->print();
            }

            if (this->child != NULL) {
                cout<<endl;
                this->child->print();
            }
        }

        /**
         * Search
         *
         * Performs search based on key
         *
         * @param Value we are searching for
         * @return Boolean value, true if value has been found, false otherwise
         */
        bool Node::search(int value) const {
            if (this->key == value)
                return true;

            if (this->child != NULL) {
                if (this->child->search(value))
                    return true;
            }

            if (this->next != NULL) {
                if (this->next->search(value))
                    return true;
            }

            return false;
        }

         /**
         * Release
         *
         * Releases current node and it's children
         *
         */
        void Node::release() {

            // TODO: Test method.

            // Do we have a child?
            if (this->child != NULL) {
                this->child->release(); // This one recursive releases children's children
                delete this->child;
                this->child = NULL;
            }

            // Release node's siblings, if present
            if (this->next != NULL) {
                this->next->release(); // This one recursive releases siblings
                delete this->next;
                this->next = NULL;
            }
        }
    }
}
